package com.appspot.zarm.controller;

import com.appspot.zarm.controller.user.User;
import com.appspot.zarm.game.Game;
import com.appspot.zarm.game.GamesStorage;
import com.appspot.zarm.game.Player;
import com.appspot.zarm.game.PlayerType;
import com.appspot.zarm.gomoku.transfer.GameExternalizer;
import com.appspot.zarm.transfer.GamesListExternalizer;
import com.appspot.zarm.transfer.Transferer;

public abstract class GameAction {

	public static final String START_ACTION = "start";
	public static final String FINISH_ACTION = "finish";
	public static final String JOIN_ACTION = "join";
	public static final String REFRESH_ACTION = "refresh";
	public static final String GET_GAMES_LIST = "getGamesList";
	
	private GamesStorage gamesStorage;
	
	public GameAction(GamesStorage gamesStorage){
		this.gamesStorage = gamesStorage;
	}
	
	protected GamesStorage getGamesStorage(){
		return gamesStorage;
	}
	
	public final GameActionResult process(User user, String action, Object data, boolean isMultiplayer, User counterUser){
		GameActionResult gameActionResult = processBaseActions(user, action, data, isMultiplayer, counterUser);
		if ( gameActionResult.isProceed() ){
			return processActions(gameActionResult, user, action, data);
		} else {
			return gameActionResult;
		}
	}

	protected abstract GameActionResult processActions(GameActionResult gameActionResult, User user, String action, Object data);
	
	protected GameActionResult processBaseActions(User user, String action, Object data, boolean isMultiplayer, User counterUser){
		GameActionResult gameActionResult = new GameActionResult();
		if (action.equals(GET_GAMES_LIST)) {
			gameActionResult.setData((GamesListExternalizer)gamesStorage);
		} else if (action.equals(START_ACTION) && isMultiplayer) {
			createMultyPlayerGame(user);
		} else if (action.equals(START_ACTION) ) {
			createSinglePlayerGame(user);
		} else if (action.equals(JOIN_ACTION) ) {
			Game game = joinGame(user, counterUser);
			gameActionResult.setData((GameExternalizer) game);
		} else if (action.equals(FINISH_ACTION)) {
			removeGame(user);
		} else if (action.equals(REFRESH_ACTION)) {
			Player player = gamesStorage.getPlayer(user);
			Game game = (Game)gamesStorage.getGame(player);
			gameActionResult.setData((GameExternalizer) game);
		} else {
			gameActionResult.setProceed(true);
		}
		return gameActionResult;
	}
	
	private Game createMultyPlayerGame(User user){
		Player player = new Player(user.getId(), PlayerType.ONE);
		Game newGame = newGame(player);
		gamesStorage.addGame(newGame);
		return newGame;
	}

	private Game createSinglePlayerGame(User user){
		Game game = createMultyPlayerGame(user);
		Player robot = new Player(user.getId(), PlayerType.TWO, true);
		game.addPlayer(robot);
		return game;
	}
	
	private Game joinGame(User user, User counterUser){
		Player rival = gamesStorage.getPlayer(counterUser);
		Game game = (Game)gamesStorage.getGame(rival);
		Player player = new Player(user.getId(), PlayerType.TWO);
		game.addPlayer(player);
		return game;
	}
	
	private void removeGame(User user){
		Player player = gamesStorage.getPlayer(user);
		gamesStorage.removeGame(player);
	}
	
	
	public abstract Game newGame(Player player);

	public abstract Transferer newTransferer(String transfererType);
}
